Shell script to trim a video with mencoder or ffmpeg
I'd previously posted a script to calculate clip duration from start/stop times for trimming with mencoder or ffmpeg, but in an effort to improve customer satisfaction (e.g. recently had to trim a bunch of Olivia's videos and couldn't be bothered to run the calc-duration script then copy/paste and edit the mencoder command), wrote a quick script that both calculates and trims.
UPDATE 2015-02-28: there are newer versions of this script:
- Shell script to trim a video clip with avconv, ffmpeg or mencoder
- Quick shell script to trim a video clip with avconv
For example, to trim a video with the start time of 45 seconds (e.g. drop the first 45 sec) and the end time of 3 min 15 sec (e.g. drop anything past that point), do:
$ trim.vid example.avi 00:00:45 00:03:15
checking input..
all good
calculating duration from start/stop times..
clip duration is 00:02:30
constructing file name for output..
trimmed video will be saved as example.trim.000045-000315.avi
trimming video..
==================================================
MEncoder 1.0rc4-4.4.5 (C) 2000-2010 MPlayer Team
success: format: 0 data: 0x0 - 0x38de94a
AVI file format detected.
[aviheader] Video stream found, -vid 0
[aviheader] Audio stream found, -aid 1
VIDEO: [XVID] 640x480 12bpp 29.970 fps 2054.6 kbps (250.8 kbyte/s)
[V] filefmt:3 fourcc:0x44495658 size:640x480 fps:29.970 ftime:=0.0334
==========================================================================
Opening audio decoder: [mp3lib] MPEG layer-2, layer-3
AUDIO: 32000 Hz, 2 ch, s16le, 192.0 kbit/18.75% (ratio: 24000->128000)
Selected audio codec: [mp3] afm: mp3lib (mp3lib MPEG layer-2, layer-3)
==========================================================================
videocodec: framecopy (640x480 12bpp fourcc=44495658)
audiocodec: framecopy (format=55 chans=2 rate=32000 bits=0 B/s=22671 sample-0)
Writing header...
ODML: Aspect information not (yet?) available or unspecified, not writing vprp header.
Setting audio delay to 0.036s.
Writing header...
ODML: Aspect information not (yet?) available or unspecified, not writing vprp header.
Setting audio delay to 0.036s.
Pos: 0.7s 22f (23%) 0.00fps Trem: 0min 0mb A-V:0.070 [0:183]
Skipping frame!
Pos: 1.0s 32f (23%) 0.00fps Trem: 0min 1mb A-V:0.067 [2011:183]
Skipping frame!
Writing index...98f (93%) 0.00fps Trem: 0min 42mb A-V:0.051 [2035:181]
Writing header...
ODML: Aspect information not (yet?) available or unspecified, not writing vprp header.
Setting audio delay to 0.036s.
Video stream: 2035.115 kbit/s (254389 B/s) size: 38162649 bytes 150.017 secs 4498 frames
Audio stream: 181.003 kbit/s (22625 B/s) size: 3394080 bytes 150.012 secs
==================================================
all done, have a fantastic day!
The script:
#!/bin/bash
# Usage: trim.vid MyVid.avi 00:30:00 00:40:00
if [ "$#" -ne "3" ]; then
echo "Error: need some args like which video file to trim and new start/stop times. Usage example:"
echo "$(basename $0) video.avi 00:30:00 00:40:00"
exit 1
else
InFile=$1
StartTime=$2
StopTime=$3
fi
CheckInput()
{
if ! [ -r $InFile ]; then
echo "Error: input file \"$InFile\" not readable"
exit 1
fi
for time in StartTime StopTime; do
if [ "$(echo $(eval echo \$$time) | grep -o ":" | wc -l)" -ne "2" ]; then
echo "Error: check $time time format, expecting two colons colons, e.g.:"
echo "00:20:00"
exit 1
fi
if [ "$(echo $(eval echo \$$time) | sed 's/://g' | wc -c)" -ne "7" ]; then
echo "Error: check $time time format, expecting six digits, e.g.:"
echo "00:20:00"
exit 1
fi
done
if [ "$StartTime" == "$StopTime" ]; then
echo "Error: same start and stop times don't make sense. I quit."
exit 1
fi
}
CalcDuration()
{
# calculates duration between start time and stop time, e.g. 00:02:00 00:10:10
# Fix:
# 1. Currently expects start hour to be less than stop hour,
# so won't work for a clip that's longer than 24 hrs, not an
# issue for me as I don't have any of those... 😉
#---------------------------------------#
starthh=$(echo $StartTime | cut -d':' -f1)
startmm=$(echo $StartTime | cut -d':' -f2)
startss=$(echo $StartTime | cut -d':' -f3)
#---------------------------------------#
stophh=$(echo $StopTime | cut -d':' -f1)
stopmm=$(echo $StopTime | cut -d':' -f2)
stopss=$(echo $StopTime | cut -d':' -f3)
#---------------------------------------#
### DEBUG
#echo " Start:" $starthh hrs $startmm min $startss sec
#echo " Stop: " $stophh hrs $stopmm min $stopss sec
#---------------------------------------#
if [[ $((10#$startmm)) -gt $((10#$stopmm)) && $((10#$startss)) -gt $((10#$stopss)) ]]; then
# start mm is greater than stop mm, so we add 60 to stop mm and
# substract 1 from stop hh
newstopmm1=$((10#$stopmm+10#60))
newstophh=$((10#$stophh-10#1))
# start ss is greater than stop ss, so we add 60 to stop ss and
# substract 1 from stop mm
newstopss=$((10#$stopss+10#60))
newstopmm=$((10#$newstopmm1-10#1))
# calculate differences
diffhh=$((10#$newstophh-10#$starthh))
diffmm=$((10#$newstopmm-10#$startmm))
diffss=$((10#$newstopss-10#$startss))
elif [[ $((10#$startmm)) -gt $((10#$stopmm)) ]]; then
# start mm is greater than stop mm, so we add 60 to stop mm and
# substract 1 from stop hh
newstopmm=$((10#$stopmm+10#60))
newstophh=$((10#$stophh-10#1))
# calculate differences
diffhh=$((10#$newstophh-10#$starthh))
diffmm=$((10#$newstopmm-10#$startmm))
diffss=$((10#$stopss-10#$startss))
elif [[ $((10#$startss)) -gt $((10#$stopss)) ]]; then
# start ss is greater than stop ss, so we add 60 to stop ss and
# substract 1 from stop mm
newstopss=$((10#$stopss+10#60))
newstopmm=$((10#$stopmm-10#1))
# calculate differences
diffhh=$((10#$stophh-10#$starthh))
diffmm=$((10#$newstopmm-10#$startmm))
diffss=$((10#$newstopss-10#$startss))
else
# all stop values are greater than start values
# calculate differences
diffhh=$((10#$stophh-10#$starthh))
diffmm=$((10#$stopmm-10#$startmm))
diffss=$((10#$stopss-10#$startss))
fi
#---------------------------------------#
# pad single digit results with a zero (if + signs contain a single digit, add a zero, then remove + signs)
pdiffhh=$(echo +$diffhh+ | sed 's/+\([0-9]\{1\}\)+/+0\1+/g;s/+//g')
pdiffmm=$(echo +$diffmm+ | sed 's/+\([0-9]\{1\}\)+/+0\1+/g;s/+//g')
pdiffss=$(echo +$diffss+ | sed 's/+\([0-9]\{1\}\)+/+0\1+/g;s/+//g')
#=======================================#
Duration=$pdiffhh:$pdiffmm:$pdiffss
#=======================================#
}
ConstructFileName()
{
ext=$(echo "$InFile" | egrep -io "\.[a-z0-9]{2,4}$")
main=$(echo "$InFile" | sed "s/$ext$//")
start=$(echo $StartTime | sed 's/://g')
stop=$(echo $StopTime | sed 's/://g')
OutFile=$main.trim.$start-$stop$ext
}
TrimVid()
{
mencoder=$(which mencoder)
if [ -x $mencoder ]; then
mencoder -ss $StartTime -endpos $Duration -oac copy -ovc copy $InFile -o $OutFile
echo "=================================================="
echo "all done, have a fantastic day!"
exit 0
fi
ffmpeg=$(which ffmpeg)
if [ -x $ffmpeg ]; then
ffmpeg -ss $StartTime -t $Duration -vcodec copy -acodec copy -i $InFile $OutFile
echo "=================================================="
echo "all done, have a fantastic day!"
exit 0
fi
echo "Error: need mencoder or ffmpeg, neither where found in your PATH.."
}
echo -e "\nchecking input.."
CheckInput
echo "all good"
echo -e "\ncalculating duration from start/stop times.."
CalcDuration
echo "clip duration is $Duration"
echo -e "\nconstructing file name for output.."
ConstructFileName
echo "trimmed video will be saved as $OutFile"
echo -e "\ntrimming video.."
echo "=================================================="
TrimVid
1 Comment
1. קידום אתרים הסבר replies at 27th August 2014, 11:05 am :
Awesome post.
Leave a comment